package com.vegetable.modules.controller.inbound;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.hutool.poi.excel.style.StyleUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.vegetable.common.annotation.PreventDuplicateSubmit;
import com.vegetable.common.annotation.SysLog;
import com.vegetable.common.utils.ExcelUtils;
import com.vegetable.common.utils.PageUtils;
import com.vegetable.common.utils.R;
import com.vegetable.modules.controller.AbstractController;
import com.vegetable.modules.entity.baseData.AddressBook;
import com.vegetable.modules.entity.finance.po.ADCanPayPO;
import com.vegetable.modules.entity.inbound.AgentDelivery;
import com.vegetable.modules.entity.inbound.AgentDeliveryDetail;
import com.vegetable.modules.entity.inbound.export.AgentDeliveryExport;
import com.vegetable.modules.entity.inbound.export.AgentDeliveryImport;
import com.vegetable.modules.entity.inbound.po.AgentDeliverySequencePO;
import com.vegetable.modules.entity.outbound.SalesOrderDetail;
import com.vegetable.modules.entity.sys.SysUserEntity;
import com.vegetable.modules.service.baseData.IAddressBookService;
import com.vegetable.modules.service.baseData.IProductSpecService;
import com.vegetable.modules.service.baseData.IProductsService;
import com.vegetable.modules.service.inbound.IAgentDeliveryService;
import com.vegetable.modules.vo.AgentDeliveryDetailVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.SecurityUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * <p>
 * 入库-代办交货 前端控制器
 * </p>
 *
 * @author wangruijie
 * @since 2024-03-07
 */
@Slf4j
@RestController
@RequestMapping("/inStorage/agentDelivery")
@AllArgsConstructor
@Api(value = "入库代办交货", tags = "入库代办交货")
public class AgentDeliveryController extends AbstractController {
    private IProductsService productsService;
    private IProductSpecService productSpecService;
    private IAgentDeliveryService agentDeliveryService;
    private IAddressBookService addressBookService;
    /**
     * 所有入库代办交货列表
     */
    @GetMapping("/list")
    @ApiOperation(value = "条件查询入库代办交货列表", notes = "条件查询入库代办交货列表")
    @SysLog("条件查询入库代办交货列表")
    public R list(@RequestParam Map<String, Object> params, @RequestHeader(value = "User-Agent", required = false) String userAgentStr){
        UserAgent userAgent = UserAgentUtil.parse(userAgentStr);
        log.info("条件查询入库代办交货列表{}, userAgent: {}", JSON.toJSONString(params), JSONObject.toJSONString(userAgent));
        params.put("userId", getUserId());
        PageUtils page = agentDeliveryService.queryPage(params);
        // 获取统计数据
        Map<String, Object> statistics = agentDeliveryService.queryPageStatistics(params);
        Map<String, Object> result = new HashMap<>();
        result.put("page", page);
        result.put("statistics", statistics);
        return R.data(result);
    }

    /**
     * 入库代办交货总表查询
     */
    @PostMapping("/sequence")
    @ApiOperation(value = "入库代办交货总表查询", notes = "入库代办交货总表查询")
    @SysLog("入库代办交货总表查询")
    public R sequence(@RequestBody AgentDeliverySequencePO po){
        log.info("入库代办交货总表查询{}", JSON.toJSONString(po));
        Map<String, Object> result = agentDeliveryService.sequence(po);
        return R.data( result);
    }

    @GetMapping("/exportSequence")
    @ApiOperation(value = "导出加工打包统计信息", notes = "导出加工打包统计信息")
    public R exportSequence(AgentDeliverySequencePO po) throws IOException {
        po.setLimit(Integer.MAX_VALUE);
        IPage<AgentDeliveryExport> result = (IPage<AgentDeliveryExport>) agentDeliveryService.sequence(po).get("records");
        List<AgentDeliveryExport> orderList = CollectionUtil.isEmpty(result.getRecords()) ? new ArrayList<>() : result.getRecords();
        // 生成导出excel对象
        ExportParams exportParams = new ExportParams();
        exportParams.setSheetName("代办交货");
        //开始导出
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, AgentDeliveryExport.class, orderList);
        workbook.createCellStyle();
        StyleUtil.createHeadCellStyle(workbook);

        String fileName = "日交接单模板" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        ExcelUtils.downLoadExcel(fileName,workbook);
        return R.success("");
    }

    /**
     * 详情入库代办交货
     */
    @SysLog(value = "详情入库代办交货")
    @GetMapping("/detailAgentDelivery")
    @ApiOperation(value = "根据id查询详情入库代办交货", notes = "根据id查询详情入库代办交货")
    public R detailAgentDelivery(Long id){
        if (id == null || id == -1){
            return R.fail("订单主键不能为空");
        }
        log.info("根据id查询详情入库代办交货：{}", JSON.toJSONString(id));
        return agentDeliveryService.detailAgentDelivery(id);

    }

    /**
     * 新增入库代办交货
     */
    @SysLog(value = "新增入库代办交货", recordEntityChange = true, entityClass = AgentDelivery.class)
    @PostMapping("/saveAgentDelivery")
    @ApiOperation(value = "新增入库代办交货", notes = "新增入库代办交货")
    public R<AgentDelivery> saveAgentDelivery(@RequestBody AgentDelivery agentDelivery){
        log.info("新增入库代办交货：{}", JSON.toJSONString(agentDelivery));
        agentDelivery.setWorkerId(getUserId());
        agentDelivery.setWorkerName(getUser().getRealName());
        agentDelivery.setCreateUserId(getUserId());
        try {
            return agentDeliveryService.saveOrEdit(agentDelivery);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("错误信息:{}",e.getLocalizedMessage());
            return R.fail(e.getMessage());
        }
    }

    /**
     * 修改入库代办交货
     */
    @SysLog(value = "修改入库代办交货", recordEntityChange = true, entityClass = AgentDelivery.class)
    @PostMapping("/updateAgentDelivery")
    @ApiOperation(value = "修改入库代办交货", notes = "修改入库代办交货")
    public R<AgentDelivery> updateAgentDelivery(@RequestBody AgentDelivery agentDelivery) throws Exception {
        log.info("修改入库代办交货：{}", JSON.toJSONString(agentDelivery));
        if (agentDelivery.getId() == null || agentDelivery.getId() == -1){
            return R.fail("订单主键不能为空");
        }
        agentDelivery.setCreateUserId(getUserId());
        return agentDeliveryService.saveOrEdit(agentDelivery);
    }

    /**
     * 提交入库代办交货
     */
    @SysLog(value = "提交入库代办交货", recordEntityChange = true, entityClass = AgentDelivery.class)
    @PostMapping("/submitAgentDelivery")
    @PreventDuplicateSubmit(expireTime = 5)
    @ApiOperation(value = "提交入库代办交货", notes = "修改入库代办交货")
    public R submitAgentDelivery(@RequestBody AgentDelivery agentDelivery) throws Exception {
        log.info("提交入库代办交货：{}", JSON.toJSONString(agentDelivery));
        agentDelivery.setCreateUserId(getUserId());
        agentDelivery.setState(3);
        return agentDeliveryService.submitAgentDelivery(agentDelivery);
    }

    /**
     * 删除入库代办交货
     */
    @SysLog(value = "删除入库代办交货", recordEntityChange = true, entityClass = AgentDelivery.class)
    @GetMapping("/deleteAgentDelivery")
    @ApiOperation(value = "根据id删除入库代办交货", notes = "根据id删除入库代办交货")
    public R deleteAgentDelivery(Long id) throws Exception {
        log.info("删除入库代办交货：{}", JSON.toJSONString(id));
        return agentDeliveryService.deleteAgentDelivery(id);
    }

    /**
     * 查询（未对账金额 > 0）可收款的待办交货
     * @param agentId null
     * @return R
     * @author wrj
     * @since 2024/4/15 上午9:31
     */
    @PostMapping("/canPaymentList")
    @ApiOperation(value = "查询可收款的待办交货", notes = "查询可收款的待办交货")
    public R canPaymentList(@RequestBody ADCanPayPO po){
        Map<String, Object> list= agentDeliveryService.canPaymentList(po);
        return R.data(list);
    }

    @GetMapping("/exportTemplate")
    @ApiOperation(value = "导出日交接单模板", notes = "导出日交接单模板")
    public R exportTemplate() throws IOException {
        List<AgentDeliveryImport> orderList = new ArrayList<>();
        // 生成导出excel对象
        ExportParams exportParams = new ExportParams();
        exportParams.setSheetName("日交接单模板");
        //开始导出
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, AgentDeliveryImport.class, orderList);
        workbook.createCellStyle();
        StyleUtil.createHeadCellStyle(workbook);

        String fileName = "日交接单模板" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        ExcelUtils.downLoadExcel(fileName,workbook);
        return R.success("");
    }

    /**
     * 批量导入待办交货
     */
    @ApiOperation("批量导入待办交货")
    @PostMapping("/uploadAgentDelivery")
    public R uploadAgentDelivery(
            @RequestParam(value = "file", required = true) MultipartFile file,
            @RequestParam(value = "isKg", required = true) Integer isKg) throws Exception {
        ImportParams importParams = new ImportParams();
        List<AgentDeliveryImport> orderList = ExcelImportUtil.importExcel(file.getInputStream(), AgentDeliveryImport.class, importParams);
        // 失败原因列表
        List<String> failReasons = new ArrayList<>();
        // 验证导入数量
        //
        if(CollectionUtil.isEmpty(orderList)){
            String failReason = "导入的表格不能为空";
            failReasons.add(failReason);
            return R.data(failReasons);
        }
        // 如果是市斤，重量/2 单价*2
        if(isKg == 1){
            for(AgentDeliveryImport order : orderList){
                order.setStandard(order.getStandard().divide(new BigDecimal("2"), 6, RoundingMode.HALF_UP));
                order.setActWeight(order.getActWeight().divide(new BigDecimal("2"), 6, RoundingMode.HALF_UP));
                order.setUnitPrice(order.getUnitPrice().multiply(new BigDecimal("2")));
                order.setWeight(order.getWeight().divide(new BigDecimal("2"), 6, RoundingMode.HALF_UP));
                order.setLossWeight(order.getLossWeight().divide(new BigDecimal("2"), 6, RoundingMode.HALF_UP));
            }
        }
        return agentDeliveryService.uploadAgentDelivery(orderList);
    }

    @SysLog(value = "矫正入库代办交货", recordEntityChange = true, entityClass = AgentDelivery.class)
    @PostMapping("/currentAgentDelivery")
    @ApiOperation(value = "提交入库代办交货", notes = "修改入库代办交货")
    public R currentAgentDelivery(@RequestBody AgentDelivery agentDelivery) throws Exception {
        log.info("矫正入库代办交货：{}", JSON.toJSONString(agentDelivery));
        agentDelivery.setCreateUserId(getUserId());
        return agentDeliveryService.currentAgentDelivery(agentDelivery);
    }

    @SysLog(value = "验证入库代办交货")
    @PostMapping("/preCurrentAgentDelivery")
    @ApiOperation(value = "验证入库代办交货", notes = "验证入库代办交货")
    public R preCurrentAgentDelivery(@RequestBody AgentDelivery agentDelivery) throws Exception {
        log.info("验证入库代办交货：{}", JSON.toJSONString(agentDelivery));
        agentDelivery.setCreateUserId(getUserId());
        return agentDeliveryService.preCurrentAgentDelivery(agentDelivery);

    }

    /**
     * 当日待办交货下商品列表
     */
    @SysLog(value = "小程序端 - 当日待办交货下商品列表")
    @GetMapping("/adTask")
    @ApiOperation(value = "当日待办交货下商品列表", notes = "当日待办交货下商品列表")
    public R todayAgentDelivery(@RequestParam(value = "orderTime", required = false) String orderTime){
        Map<String, Object> result = new HashMap<>();
        SysUserEntity user = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
        String mobile = user.getMobile();
        AddressBook ab = addressBookService.selectByMobile(mobile);
        log.info("当前登录用户是:{}， 对应的客户是:{}, 查询时间是:{}", user, ab, orderTime);
        if(ObjectUtil.isNull(ab)){
            result.put("agentName", "游客");
            result.put("orders", new ArrayList<>());
        }else {
            List<AgentDelivery> voList = agentDeliveryService.todayAgentDelivery(ab.getId(), orderTime);
            result.put("agentName", ab.getNoteName());
            result.put("orders", voList);
        }
        return R.data(result);
    }

    @GetMapping("/lastOrder")
    @ApiOperation(value = "查询客户最近的一次代办订单", notes = "查询客户最近的一次代办订单", response = SalesOrderDetail.class)
    public R lastOrder(Long customerId) throws Exception {
        if(ObjectUtil.isNull(customerId)){
            throw new Exception("代办ID不能为空");
        }
        List<AgentDeliveryDetail> details = agentDeliveryService.lastOrder(customerId);
        return R.data(details);
    }

    @SysLog(value = "小程序提交代办任务")
    @PostMapping("/confirm")
    @ApiOperation(value = "小程序提交代办任务", notes = "小程序提交代办任务")
    public R<AgentDelivery> confirm(@RequestBody AgentDelivery agentDelivery) throws Exception {
        log.info("小程序提交代办任务：{}", JSON.toJSONString(agentDelivery));
        // 代办交货订单的id
        Long adId = agentDelivery.getId();
        AgentDelivery exist = agentDeliveryService.getById(adId);
        if(Objects.isNull(exist)){
            log.info("小程序提交代办任务时 根据id：{}没有发现该任务", adId);
            return R.fail("采购人任务不存在，请联系管理员.");
        }
        AddressBook ab = addressBookService.selectByMobile(getUser().getMobile());
        if(Objects.isNull(ab)){
            log.info("小程序提交代办任务时 根据当前登录人的电话：{}没有发现该代办", getUser().getMobile());
            return R.fail("采购人任务不存在，请联系管理员.");
        }
        if(!ab.getId().equals(exist.getAgentId())){
            log.error("通过id:{}找到订单：{},该订单的agentId是{},但当前操作人是{}", adId, exist.getDocNo(), exist.getAgentId(), ab.getId());
            return R.fail("您无权操作该订单.");
        }
        return agentDeliveryService.confirm(agentDelivery);
    }
}
